# 处理依赖数据
# sys.path.append('F:/A_RuanJian/Py_project/imooc/')
from mysql_connect.get_data import GetData
from jsonpath_rw import parse
from util.operation_json import OperetionJson
from dataconfig.file_config import FilePath
from logs.user_log import UserLog
from run_assert.cookie_token import CookieToken
from util.operation_yaml import OperationYaml
from run_assert.assert_run import AssertRun
from mysql_connect.mysql_db import MysqlDB
from mysql_connect import col_name as col
mysql = MysqlDB()
data_db = GetData()
op_json = OperetionJson()
path = FilePath()
log = UserLog().get_log()
op_yaml = OperationYaml()
cookie_key = '__outh'
yaml_key = 'pre_res_value'
assert_run = AssertRun()
run_cookie_token = CookieToken()


class DependdentData:

    # 当前case为前置用例，执行请求，并提取和写入可能会被后面用例需要的值
    def run_pre_case_write(self, sql_id, case_id, pre_key, token, cookies, method, url, request_data_dict, headers, header_type, expect, result_key):
        res = run_cookie_token.cookie_token(token, cookies, method, url, request_data_dict, headers, header_type)
        res_s = res.json()
        pre_value = self.get_pre_value(pre_key, res_s)
        self.write_pre_value(pre_value, case_id)
        flag, msg = assert_run.assert_main(expect, result_key, res,sql_id=sql_id)
        return flag, msg

    def write_pre_value(self, pre_value, case_id):
        log.debug('更新依赖数据')
        read_yaml = op_yaml.read_data()
        read_yaml[yaml_key][case_id] = pre_value
        op_yaml.write_data(read_yaml)

    # 尝试先从文件中获取依赖数据
    def get_pre_value_by_file(self, case_id):
        value = op_yaml.read_data()[yaml_key][case_id]
        return value

    # 清除已经使用过的依赖数据
    def delete_pre_value(self, case_id, delete=True):
        if delete:
            log.debug('清除已经使用过的依赖数据')
            read_yaml = op_yaml.read_data()
            read_yaml[yaml_key][case_id] = None
            op_yaml.write_data(read_yaml)

    # 执行依赖测试，并判断是否需要添加cookie，然后返回结果
    def run_pre(self, sql_id, case_id, case_dict, pre_pre_res_value=None):
        case_list = data_db.get_data_list(case_dict)
        (case_id, case_name, url_host, cookie, token, header_dict, header_type, method, data_dict,
         pre_case_id, pre_case_key, pos_case_key, expect, result_key) = case_list
        if pre_pre_res_value :
            data_dict = self.get_pre_data_dict(data_dict, pos_case_key, pre_pre_res_value)
        res = run_cookie_token.cookie_token(token, cookie, method, url_host, data_dict, header_dict, header_type)
        try:
            res_dict = res.json()
        except:
            # res_r = res.text
            res_dict = None
            log.error('错误,依赖接口的响应结果不是dict')
        # log.debug('前置请求 "%s" 的响应结果为：%s；type："%s"' %(pre_case_id, res_r, type(res_r)))
        pre_assert = assert_run.assert_main_pre(expect, result_key, res, case_id, sql_id=sql_id)
        return res_dict, pre_assert


    def get_value_by_key(self,sql_id, pre_case_id, pre_pre_res_value=None):
        # depend_key = self.data.get_depend_key(row)
        case_dict = mysql.get_case_dict_by_CaseID(pre_case_id)
        pre_key = case_dict[col.pre_case_key]
        res_dict, pre_assert = self.run_pre(sql_id, pre_case_id, case_dict, pre_pre_res_value)
        depend_res_value = self.get_pre_value(pre_key, res_dict)
        return depend_res_value, pre_assert

    def get_pre_value(self, pre_key, res_dict):
        log.debug('前置接口的响应结果为: \n%s' % res_dict)
        log.debug('前置的key为：%s' % pre_key)
        try:
            male = parse(pre_key).find(res_dict)
            depend_res_value = [match.value for match in male][0]
        except:
            print ('错误：依赖数据获取失败')
            log.error('错误：依赖数据获取失败')
        else:
            # print (a01)
            log.debug('获取的value为："%s"；(from前置请求的响应结果中)' %depend_res_value)
            return depend_res_value

    # 获取后置case的key
    def get_pos_data_key(self,key):
        log.debug('后置请求数据的key为"%s"' %key)
        if key == "":
            return None
        elif 'list' in key:
            key_split = key.split(".")
            return int(key_split[1])
        else:
            # 将excel上的依赖key分割，并转格式为int（if 可以转的话）
            # 如 products.0.quantity
            key_split = key.split(".")
            excel_int_list = []
            for i in key_split:
                try:
                    int_i = int(i)
                except:
                    res = i
                else:
                    res = int_i
                excel_int_list.append(res)
            log.debug('后置请求数据的key_list为"%s"' %excel_int_list)
            return excel_int_list

    def get_pre_data(self, sql_id, pre_case_id, pos_data_dict, pos_data_key):
        log.debug('尝试从文件中获取依赖数据：{}'.format(pre_case_id))
        pre_res_value = self.get_pre_value_by_file(pre_case_id)
        pre_assert = '';pre_assert_02 = ''
        if pre_res_value:
            log.debug('获取依赖数据成功：{}'.format(pre_res_value))
            self.delete_pre_value(pre_case_id, delete=False)
        else:
            log.debug('获取依赖数据失败，准备从前置请求中获取')
            # pre_pre_case_id = self.get_excel_list_by_ID(pre_case_id)[col_num.case_depend_id]
            case_mysql = mysql.get_case_dict_by_CaseID(pre_case_id)
            pre_pre_case_id = case_mysql[col.pre_case_id]
            pre_sql_id = case_mysql[col.sql_id]
            pre_pre_res_value = None
            if pre_pre_case_id:
                log.debug('该前置请求也需要依赖数据，尝试从文件中获取二层依赖数据：{}'.format(pre_pre_case_id))
                pre_pre_res_value = self.get_pre_value_by_file(pre_pre_case_id)
                if pre_pre_res_value:
                    pre_pre_res_value = pre_pre_res_value
                    log.debug('获取成功, 二层依赖数据为：{}'.format(pre_pre_res_value))
                    self.delete_pre_value(pre_pre_case_id, delete=False)
                else:
                    log.debug('获取失败，准备执行二层前置请求')
                    case_mysql = mysql.get_case_dict_by_CaseID(pre_pre_case_id)
                    pre_x3_case_id = case_mysql[col.pre_case_id]
                    pre_pre_sql_id = case_mysql[col.sql_id]
                    if pre_x3_case_id:
                        print('该二层前置请求需要依赖三层前置请求"%s"，请在excel中先执行三层请求！' % pre_x3_case_id)
                    else:
                        pre_pre_res_value, pre_assert_02 = self.get_value_by_key(pre_pre_sql_id, pre_pre_case_id)
            else:
                log.debug('前置请求不需要依赖数据，准备发送前置请求')
            # 发起前置请求，并获取返回的依赖key: 获取将key分隔，将list转格式；然后获取list的长度
            log.debug('执行一层前置请求,\n\ncase_id切换为"%s"，执行前置接口' % pre_case_id)
            pre_res_value, pre_assert = self.get_value_by_key(pre_sql_id, pre_case_id, pre_pre_res_value)
        pos_data_dict = self.get_pre_data_dict(pos_data_dict, pos_data_key, pre_res_value)
        return pos_data_dict, pre_assert, pre_assert_02

    def get_pre_data_dict(self, pos_data_dict, pos_data_key, pre_res_value):
        key_list = self.get_pos_data_key(pos_data_key)
        log.debug('后置请求原始的request_data的类型，值分别为：%s \n%s' % (type(pos_data_dict), pos_data_dict))
        if type(key_list) == int:
            # 当key为int时，把data转换成为list
            data_dict = list(pos_data_dict)
            data_dict[0] = pre_res_value
            return data_dict
        else:
            # 获取数据依赖字段list_key
            try:
                len01 = len(key_list)
                log.debug('key_list的长度为："%s"' % len01)
                # 根据处理后的key数据，更新后置请求的数据，目前支持的索引最大深度为3
                if len01 == 1:
                    b01 = key_list[0]
                    pos_data_dict[b01] = pre_res_value
                elif len01 == 2:
                    # b01 = int_list[0];b02 = int_list[1]
                    b01, b02 = key_list
                    pos_data_dict[b01][b02] = pre_res_value
                elif len01 == 3:
                    # b01 = int_list[0];b02 = int_list[1];b03 = int_list[2]
                    b01, b02, b03 = key_list
                    log.debug('字符串格式为："%s", "%s"' % (type(b02), b02))
                    pos_data_dict[b01][b02][b03] = pre_res_value
                log.debug('更新后的依赖数据为：%s' % pos_data_dict)
            except:
                log.error('依赖数据更新失败！请检查相关参数，还有参数的格式')
            return pos_data_dict


if __name__ == '__main__':
    # print(a01)
    pass



